﻿//  此文件中模拟所有的CPU指令
namespace DA6502.CPU
{
    using addr = System.UInt16;

    /// <summary>
    /// CPU指令集的实现
    /// 
    /// 注意：要求此处不出现取指操作
    /// </summary>
    public partial class CPU
    {

        #region ==============================| 传输指令 |==============================
        //================================================================================
        //  Transfer Instructions: Load, store, interregister transfer
        //  传输指令
        //================================================================================

        /// <summary>
        /// 从内存中取值送入变址寄存器A
        /// </summary>
        /// <param name="op"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Lda(byte op)
        {
            A = op;
            N = IsNegative(A);
            Z = A == 0;
        }
        /// <summary>
        /// 从内存中取值送入变址寄存器A
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Lda(addr ad) => Lda(IO[ad]);

        /// <summary>
        /// 立即数 送 X
        /// </summary>
        /// <param name="op"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Ldx(byte op)
        {
            X = op;
            N = IsNegative(X);
            Z = X == 0;
        }
        /// <summary>
        /// 内存 送 X
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Ldx(addr ad) => Ldx(IO[ad]);

        /// <summary>
        /// 立即数 送 Y
        /// </summary>
        /// <param name="op"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Ldy(byte op)
        {
            Y = op;
            N = IsNegative(Y);
            Z = Y == 0;
        }
        /// <summary>
        /// 内存 送 Y
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Ldy(addr ad) => Ldy(IO[ad]);

        /// <summary>
        /// 存 A
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Sta(addr ad) => IO[ad] = A;

        /// <summary>
        /// 存 X
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Stx(addr ad) => IO[ad] = X;

        /// <summary>
        /// 存 Y
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Sty(addr ad) => IO[ad] = Y;

        /// <summary>
        /// A 送 X
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Tax()
        {
            X = A;
            N = IsNegative(X);
            Z = X == 0;
        }

        /// <summary>
        /// A 送 Y
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Tay()
        {
            Y = A;
            N = IsNegative(A);
            Z = A == 0;
        }

        /// <summary>
        /// SP 送 X
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Tsx()
        {
            X = S;
            N = IsNegative(X);
            Z = X == 0;
        }

        /// <summary>
        /// X 送 A
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Txa()
        {
            A = X;
            N = IsNegative(A);
            Z = A == 0;
        }

        /// <summary>
        /// X 送 SP
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Txs() => S = X;

        /// <summary>
        /// Y 送 A
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Tya()
        {
            A = Y;
            N = IsNegative(A);
            Z = A == 0;
        }

        #endregion

        #region ==============================| 栈指令 |==============================

        //================================================================================
        //  Stack Instructions
        //  栈指令
        //  栈指令将累加器或状态寄存器(标志)传送到堆栈中或从堆栈中传送出去。
        //  处理器堆栈是后进先出(LIFO)堆栈，长度为256字节，实现地址为$0100 - $01FF。
        //  当新的值被推送到堆栈上时，堆栈会向下增长，当前插入点保存在堆栈指针寄存器中。
        //  当一个字节被推入堆栈时，它将被存储在当前堆栈指针的值所指示的地址中，然后该值将减1。
        //  相反，当从堆栈中提取一个值时，堆栈指针将递增。
        //  堆栈指针可以被TSX和TXS指令访问。
        //================================================================================

        /// <summary>
        /// 压 A 入栈
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Pha() => PushByte(A);

        /// <summary>
        /// 压 P 入栈
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Php() => PushByte((byte)(P | 0b00110000));

        /// <summary>
        /// 弹 A 出栈
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Pla()
        {
            A = PopByte();
            N = IsNegative(A);
            Z = A == 0;
        }

        /// <summary>
        /// 弹 P 出栈
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Plp() => P = (byte)((PopByte() & ~FLAG_MASK[FLAGS.B]) | FLAG_MASK[FLAGS.U]);

        #endregion

        #region ==============================| 自增自减指令 |==============================

        //================================================================================
        //  Decrements & Increments
        //================================================================================

        /// <summary>
        /// 内存 减1
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Dec(addr ad)
        {
            IO[ad]--;
            Z = IO[ad] == 0;
            N = IsNegative(IO[ad]);
        }

        /// <summary>
        /// X 减1
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Dex()
        {
            X--;
            N = IsNegative(X);
            Z = X == 0;
        }

        /// <summary>
        /// Y 减1
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Dey()
        {
            Y--;
            N = IsNegative(Y);
            Z = Y == 0;
        }

        /// <summary>
        /// 内存 加1
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Inc(addr ad)
        {
            IO[ad]++;
            Z = IO[ad] == 0;
            N = IsNegative(IO[ad]);
        }

        /// <summary>
        /// X 加1
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Inx()
        {
            X++;
            N = IsNegative(X);
            Z = X == 0;
        }

        /// <summary>
        /// Y 加1
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Iny()
        {
            Y++;
            N = IsNegative(Y);
            Z = Y == 0;
        }

        #endregion

        #region ==============================| 数学运算指令 |==============================

        //================================================================================
        //  Arithmetic Operations
        //  数学运算指令
        //================================================================================

        /// <summary>
        /// 带进位加法
        /// </summary>
        /// <param name="op">立即数</param>
        protected void Adc(byte op)
        {
            short r = (short)(A + op + (C ? 1 : 0));
            Z = (r & 0x00FF) == 0;
            N = IsNegative((byte)(r % 0x100));
            C = r > 0xFF;

            //  V   = op[7] ^ A[7] ^ (A+op)[7] ^ C
            V = ((A & 0x80) ^ (op & 0x80) ^ (r & 0x0080)) > 0;
            V = V != C;

            A = (byte)(r & 0x00FF);

        }
        /// <summary>
        /// 带进位加法
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Adc(addr ad)
        {
            Adc(IO[ad]);
        }

        /// <summary>
        /// 带借位减法
        /// </summary>
        /// <param name="op"></param>
        protected void Sbc(byte op)
        {
            short r = (short)(A - op - (C ? 0 : 1));
            Z = (r & 0xFF) == 0;
            N = IsNegative((byte)(r & 0x00FF));

            //  借位标志
            C = r >= 0;
            V = (IsNegative(A) != IsNegative(op)) != IsNegative((byte)(r & 0x00FF)) != ((r & 0x0100) != 0);
            //if (V) C = false;
            A = (byte)(r & 0x00FF);
        }

        /// <summary>
        /// 带借位减法
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Sbc(addr ad)
        {
            Sbc(IO[ad]);
        }

        #endregion

        #region ==============================| 逻辑运算指令 |==============================

        //================================================================================
        //  Logical Operations
        //  逻辑运算指令
        //================================================================================

        /// <summary>
        /// 累加寄存器A 与立即数op进行逻辑与运算，结果存回A，同时影响标志位N和Z
        /// </summary>
        /// <param name="op"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void And(byte op)
        {
            A &= op;
            N = IsNegative(A);
            Z = A == 0;
        }

        /// <summary>
        /// 累加寄存器A 与 ad 地址的值（1字节）进行逻辑与运算，结果存回A，同时影响标志位N和Z
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void And(addr ad) => And(IO[ad]);

        /// <summary>
        /// 累加寄存器A 与立即数op进行逻辑异或运算，结果存回A，同时影响标志位N和Z
        /// </summary>
        /// <param name="op"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Eor(byte op)
        {
            A ^= op;
            N = IsNegative(A);
            Z = A == 0;
        }

        /// <summary>
        /// 累加寄存器A 与 ad 地址的值（1字节）进行逻辑异或运算，结果存回A，同时影响标志位N和Z
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Eor(addr ad) => Eor(IO[ad]);

        /// <summary>
        /// 累加寄存器A 与立即数op进行逻辑或运算，结果存回A，同时影响标志位N和Z
        /// </summary>
        /// <param name="op"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Ora(byte op)
        {
            A |= op;
            N = IsNegative(A);
            Z = A == 0;
        }

        /// <summary>
        /// 累加寄存器A 与 ad 地址的值（1字节）进行逻辑或运算，结果存回A，同时影响标志位N和Z
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Ora(addr ad)
        {
            A |= IO[ad];
            N = IsNegative(A);
            Z = A == 0;
        }

        #endregion

        #region ==============================| 移位运算指令 |==============================

        //================================================================================
        //  Shift & Rotate Instructions
        //  移位运算指令
        //================================================================================

        /// <summary>
        /// 算术左移。该指令将累加器所有位移左一位。第0位设置为0，第7位放置进位标志。
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Asl()
        {
            C = (A & 0x80) > 0;
            A <<= 1;
            N = IsNegative(A);
            Z = A == 0;
        }

        /// <summary>
        /// 算术左移。该指令将内存内容的所有位移左一位。第0位设置为0，第7位放置进位标志。
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Asl(addr ad)
        {
            C = (IO[ad] & 0x80) > 0;
            IO[ad] <<= 1;
            N = IsNegative(IO[ad]);
            Z = IO[ad] == 0;
        }

        /// <summary>
        /// 算术右移。该指令将累加器所有位右移一位，第7位设置为0.移出的第0位放入进位标志C。
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Lsr()
        {
            C = (A & 0x01) > 0;
            A >>= 1;
            N = IsNegative(A);
            Z = A == 0;
        }

        /// <summary>
        /// 算术右移。该指令将内存内容的所有位右移一位，第7位设置为0.移出的第0位放入进位标志C。
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Lsr(addr ad)
        {
            C = (IO[ad] & 0x01) > 0;
            IO[ad] >>= 1;
            N = IsNegative(IO[ad]);
            Z = IO[ad] == 0;
        }

        /// <summary>
        /// 循环左移。该指令将进位标志做为第8位，与累加器组合成9位二进位，并循环左移一位。
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Rol()
        {
            bool oC = C;
            C = (A & 0x80) > 0;
            A <<= 1;
            A |= (byte)(oC ? 0x01 : 0x00);
            N = IsNegative(A);
            Z = A == 0;
        }

        /// <summary>
        /// 循环左移。该指令将进位标志做为第8位，与内存的内容组合成9位二进位，并循环左移一位。
        /// </summary>
        /// <param name="ad"></param>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Rol(addr ad)
        {
            bool oC = C;
            C = (IO[ad] & 0x80) > 0;
            IO[ad] <<= 1;
            IO[ad] |= (byte)(oC ? 0x01 : 0x00);
            N = IsNegative(IO[ad]);
            Z = IO[ad] == 0;
        }

        /// <summary>
        /// 循环右移。该指令将进位标志做为第0位，与累加器组合成9位二进位，并循环右移一位。
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Ror()
        {
            bool oC = C;
            C = (A & 0x01) > 0;
            A >>= 1;
            A |= (byte)(oC ? 0x80 : 0x00);
            N = IsNegative(A);
            Z = A == 0;
        }

        /// <summary>
        /// 循环右移。该指令将进位标志做为第0位，与内存的内容组合成9位二进位，并循环右移一位。
        /// </summary>
        /// <param name="ad"></param>
        protected void Ror(addr ad)
        {
            bool oC = C;
            C = (IO[ad] & 0x01) > 0;
            IO[ad] >>= 1;
            IO[ad] |= (byte)(oC ? 0x80 : 0x00);
            N = IsNegative(IO[ad]);
            Z = IO[ad] == 0;
        }

        #endregion

        #region ==============================| 标志位指令 |==============================

        //================================================================================
        //  Flag Instructions
        //  标志位指令
        //================================================================================

        /// <summary>
        /// 清 C
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Clc() => C = false;

        /// <summary>
        /// 清D
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Cld() => D = false;

        /// <summary>
        /// 清I
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Cli() => I = false;

        /// <summary>
        /// 清V
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Clv() => V = false;

        /// <summary>
        /// 设C
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Sec() => C = true;

        /// <summary>
        /// 设D
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Sed() => D = true;

        /// <summary>
        /// 设I
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Sei() => I = true;

        #endregion

        #region ==============================| 比较 |==============================

        //================================================================================
        //  Comparisons
        //  比较
        //  一般来说，比较指令从给定的寄存器中减去操作数而不影响这个寄存器。
        //  标志仍然设置为正常的减法，因此这两个值的关系可以通过0、进位和负标志访问。
        //  计算 Register - Op
        //  若 Register < op，则 Z=0， C=0， N为结果的符号位（第7位）
        //  若 Register = op，则 Z=1， C=1， N为0
        //  若 Register > op，则 Z=0， C=1， N为结果的符号位（第7位）
        //================================================================================

        /// <summary>
        /// 累加器A - 立即数op，结果不保存。
        /// </summary>
        protected void Cmp(byte op)
        {

            byte r = (byte)(A - op);
            if (A < op)
            {
                Z = false;
                C = false;
                N = IsNegative(r);
            }
            else if (A == op)
            {
                Z = true;
                C = true;
                N = false;
            }
            else
            {
                Z = false;
                C = true;
                N = IsNegative(r);
            }
        }

        /// <summary>
        /// 累加器A - 内存值，结果不保存。
        /// </summary>
        /// <returns></returns>
        protected void Cmp(addr ad) => Cmp(IO[ad]);

        /// <summary>
        /// 变址寄存器X与立即数op比较，结果不保存
        /// </summary>
        /// <param name="ad"></param>
        protected void Cpx(byte op)
        {

            byte r = (byte)(X - op);
            if (X < op)
            {
                Z = false;
                C = false;
                N = IsNegative(r);
            }
            else if (X == op)
            {
                Z = true;
                C = true;
                N = false;
            }
            else
            {
                Z = false;
                C = true;
                N = IsNegative(r);
            }
        }

        /// <summary>
        /// 变址寄存器X与存储器比较，结果不保存
        /// </summary>
        /// <param name="ad"></param>
        protected void Cpx(addr ad) => Cpx(IO[ad]);

        /// <summary>
        /// 变址寄存器Y与立即数op比较，结果不保存
        /// </summary>
        /// <param name="ad"></param>
        protected void Cpy(byte op)
        {

            byte r = (byte)(Y - op);
            if (Y < op)
            {
                Z = false;
                C = false;
                N = IsNegative(r);
            }
            else if (Y == op)
            {
                Z = true;
                C = true;
                N = false;
            }
            else
            {
                Z = false;
                C = true;
                N = IsNegative(r);
            }
        }

        /// <summary>
        /// 变址寄存器Y与存储器比较，结果不保存
        /// </summary>
        /// <param name="ad"></param>
        protected void Cpy(addr ad) => Cpy(IO[ad]);

        #endregion

        #region ==============================| 条件分支指令 |==============================

        //================================================================================
        //  Conditional Branch Instructions
        //  条件分支指令
        //================================================================================

        /// <summary>
        /// C=1 分支
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Bcs(addr ad) => PC = C ? ad : PC;

        /// <summary>
        /// C=0 分支
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Bcc(addr ad) => PC = C ? PC : ad;

        /// <summary>
        /// Z=1 分支
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Beq(addr ad) => PC = Z ? ad : PC;

        /// <summary>
        /// Z=0 分支
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Bne(addr ad) => PC = Z ? PC : ad;

        /// <summary>
        /// N=1 分支
        /// </summary> 
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Bmi(addr ad) => PC = N ? ad : PC;

        /// <summary>
        /// N=0 分支
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Bpl(addr ad) => PC = N ? PC : ad;

        /// <summary>
        /// V=1 分支
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Bvs(addr ad) => PC = V ? ad : PC;

        /// <summary>
        /// V=0 分支
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Bvc(addr ad) => PC = V ? PC : ad;

        #endregion

        #region ==============================| 跳转及子程序 |==============================

        //================================================================================
        //  Jumps & Subroutines
        //  跳转及子程序
        //  当返回地址被压入堆栈或从堆栈中取出时，JSR和RTS会影响堆栈。
        //  (JSR压栈是先高字节，后低字节)
        //================================================================================

        /// <summary>
        /// 无条件跳转
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Jmp(addr ad) => PC = ad;

        /// <summary>
        /// 跳转到子程序
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Jsr(addr ad)
        {
            PushAddr((addr)(PC - 1));
            PC = ad;
        }

        /// <summary>
        /// 子程序返回
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Rts() => PC = (addr)(PopAddr() + 1);

        #endregion

        #region ==============================| 中断 |==============================

        //================================================================================
        //  Interrupts
        //  中断
        //  一个硬件中断(可屏蔽的IRQ和不可屏蔽的NMI)，将导致处理器将PC压栈，然后是状态寄存器P压栈。
        //  (堆栈现在将包含：从底部或从最近添加的字节看，P PC-L PC-H。栈为负增长，所以栈指针指向状态寄存器存储内容下面的地址。)
        //  然后，处理器将把它的控制流转移到两个字大小的中断向量(IRQ和NMI)提供的地址上。
        //  设置中断禁用标志将禁止执行IRQ，但不会禁止NMI的执行，NMI无论如何都会被执行。
        //  中断指令(BRK)的行为类似于NMI，但将把PC+2的值推到堆栈上用作返回地址。
        //  同样，与任何软件启动的状态寄存器到堆栈的传输一样，将会发现在推入堆栈的相应值上设置了中断标志。
        //  在任何情况下，当控制被转移到由相应的中断向量指定的中断处理程序时，中断禁用标志被设置为禁止任何进一步的IRQ。
        //  RTI指令从堆栈中恢复状态寄存器，并在其他方面与JSR指令类似。
        //  (break标志总是被忽略，因为状态是从堆栈中读取的，因为它不是一个真正的处理器标志。)
        //================================================================================

        /// <summary>
        /// BRK中断
        /// BRK启动一个类似于硬件中断(IRQ)的软件中断。
        /// 推送到堆栈的返回地址是PC+2，提供了一个额外的字节间距作为中断标记(确定中断的原因)。
        /// 状态寄存器将被推入堆栈，中断标志设置为1。
        /// 然而，当在RTI期间或通过PLP指令检索时，中断标志将被忽略。
        /// 中断禁用标志不会自动设置。
        /// </summary>
        protected void Brk()
        {
            I = true;
            B = true;
            U = true;

            IF();   //  推送到堆栈的返回地址是PC+2
            PushAddr(PC);
            PushByte(P);

            byte low = IO[INTERRUPT_VECTOR_IRQ];
            byte high = IO[INTERRUPT_VECTOR_IRQ + 1];
            addr ad = AddrJoin(high, low);
            PC = ad;
        }

        /// <summary>
        /// 中断返回
        /// </summary>
        protected void Rti()
        {
            P = PopByte();
            B = false;
            U = true;
            PC = PopAddr();
        }

        #endregion

        #region ==============================| 其它指令 |==============================

        //================================================================================
        //  Others
        //  其它指令
        //================================================================================
        /// <summary>
        /// KIL
        /// CPU挂起，需要Reset才能再次运行
        /// 别名：JAM、HLT
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Kil() => kilFlag = true;

        /// <summary>
        /// 空操作
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Nop() { }

        /// <summary>
        /// 空操作
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Nop(byte op) { }

        /// <summary>
        /// 空操作
        /// </summary>
        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
        protected void Nop(addr ad) { }

        /// <summary>
        /// 位测试
        /// 该指令用于测试目标存储单元中是否设置了一个或多个位。 
        /// 将A中的掩码图案与内存中的值进行“与”运算以设置或清除零标志，但结果不会保留。 
        /// 来自存储器的值的第7位被复制到N、第6位被复制到V标志中。
        /// </summary>
        /// <param name="ad"></param>
        protected void Bit(addr ad)
        {
            byte r = (byte)(A & IO[ad]);
            Z = r == 0;
            N = (0x80 & IO[ad]) > 0;
            V = (0x40 & IO[ad]) > 0;
        }

        #endregion

        #region ==============================| 非官方公开指令 |==============================

        //================================================================================
        //  Illegal Opcodes
        //  非法（非官方公开）的操作码
        //================================================================================

        /// <summary>
        /// ASL + ORA
        /// </summary>
        /// <param name="ad"></param>
        protected void Slo(addr ad)
        {
            Asl(ad);
            Ora(ad);
        }

        /// <summary>
        /// ROL + AND
        /// </summary>
        /// <param name="ad"></param>
        protected void Rla(addr ad)
        {
            Rol(ad);
            And(ad);
        }

        /// <summary>
        /// LSR + EOR
        /// </summary>
        /// <param name="ad"></param>
        protected void Sre(addr ad)
        {
            Lsr(ad);
            Eor(ad);
        }

        /// <summary>
        /// ROR + ADC
        /// </summary>
        /// <param name="ad"></param>
        protected void Rra(addr ad)
        {
            Ror(ad);
            Adc(ad);
        }

        /// <summary>
        /// A and X -> M
        /// </summary>
        /// <param name="ad"></param>
        protected void Sax(addr ad)
        {
            IO[ad] = (byte)(A & X);
        }

        /// <summary>
        /// LDA + LDX
        /// </summary>
        /// <param name="ad"></param>
        protected void Lax(addr ad)
        {
            Lda(ad);
            Ldx(ad);
        }

        /// <summary>
        /// DEC + CMP
        /// </summary>
        /// <param name="ad"></param>
        protected void Dcp(addr ad)
        {
            Dec(ad);
            Cmp(ad);
        }

        /// <summary>
        /// INC + SBC
        /// </summary>
        /// <param name="ad"></param>
        protected void Isc(addr ad)
        {
            Inc(ad);
            Sbc(ad);
        }

        /// <summary>
        /// A and op, M7 -> C
        /// </summary>
        /// <param name="op"></param>
        protected void Anc(byte op)
        {
            /// 这个命令只执行AND操作，但是第7位被放入进位，就像执行了ASL/ROL一样。
            A &= op;
            Z = A == 0;
            N = IsNegative(A);
            C = N;
        }

        /// <summary>
        /// AND + LSR
        /// </summary>
        /// <param name="op"></param>
        protected void Alr(byte op)
        {
            A &= op;
            C = (A & 0x01) > 0;
            A >>= 1;
            Z = A == 0;
            N = IsNegative(A);
        }

        /// <summary>
        /// AND + ROR
        /// </summary>
        /// <param name="op"></param>
        protected void Arr(byte op)
        {
            //  这个命令的一部分是一些ADC机制。
            //  以下效果出现在AND之后，但ROR之前:
            //  V-Flag被设置为 (A & #{imm}) + #{imm}
            //  位0不会进入进位，但位7会与进位交换。
            A &= op;
            short r = (short)((A & op) + op);
            V = r > sbyte.MaxValue || r < sbyte.MinValue;
            bool oC = C;
            A >>= 1;
            C = (A & 0x01) > 0;
            A |= (byte)(oC ? 0x80 : 0x00);
        }

        /// <summary>
        /// * AND X + AND op
        /// </summary>
        /// <param name="op"></param>
        protected void Xaa(byte op)
        {
            //  一部分6502芯片中此指令非常不稳定
            A = X;
            A &= op;
            Z = A == 0;
            N = IsNegative(A);
        }

        /// <summary>
        /// LDA + LDX
        /// </summary>
        /// <param name="op"></param>
        protected void Lax(byte op)
        {
            A = op;
            X = op;
            Z = A == 0;
            N = IsNegative(A);
        }

        /// <summary>
        /// A AND X -> M
        /// </summary>
        /// <param name="op"></param>
        protected void Axs(byte op)
        {
            //      AXS #{imm} = A&X - #{imm} into X
            //  同时执行CMP和DEX，所以减号S设置的标志是CMP，而不是SBC。
            byte r = ((byte)(A & X));
            Z = r == 0;
            N = IsNegative(r);
            X = (byte)(r - op);
            C = r < op;
        }

        /// <summary>
        /// Stores A AND X AND (high-byte of addr. + 1) at addr.
        /// </summary>
        /// <param name="ad"></param>
        protected void Ahx(addr ad) => IO[ad] = (byte)(A & X & AddrHigh(ad));

        /// <summary>
        /// Stores Y AND (high-byte of addr. + 1) at addr.
        /// </summary>
        /// <param name="ad"></param>
        protected void Shy(addr ad) => IO[ad] = (byte)(Y & AddrHigh(ad));

        /// <summary>
        /// Stores X AND (high-byte of addr. + 1) at addr.
        /// </summary>
        /// <param name="ad"></param>
        protected void Shx(addr ad) => IO[ad] = (byte)(X & AddrHigh(ad));

        /// <summary>
        /// Puts A AND X in SP and stores A AND X AND (high-byte of addr. + 1) at addr.
        /// </summary>
        /// <param name="ad"></param>
        protected void Tas(addr ad)
        {
            S = (byte)(A & X);
            IO[ad] = (byte)(A & X & AddrHigh(ad));
        }

        /// <summary>
        /// M AND SP -> A, X, SP
        /// </summary>
        /// <param name="ad"></param>
        protected void Las(addr ad)
        {
            A = (byte)(S & IO[ad]);
            X = A;
            S = A;
        }

        /// <summary>
        /// ASL oper + ORA oper
        /// </summary>
        /// <param name="ad"></param>
        protected void SLO(addr ad)
        {
            Asl(ad);
            Ora(ad);
        }

        #endregion
    }
}